.PHONY: help default build run run-mt test test-run test-teardown mocks

GO=go
LDFLAGS?=-s -w
TESTFILE=_testok
MOUNT_PATH=/local

# go tools versions
GOLANGCI=github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.5.0
gofumpt=mvdan.cc/gofumpt@v0.9.1
govulncheck=golang.org/x/vuln/cmd/govulncheck@latest
goimports=golang.org/x/tools/cmd/goimports@latest
mockgen=go.uber.org/mock/mockgen@v0.6.0
gotestsum=gotest.tools/gotestsum@v1.12.3
protoc-gen-go=google.golang.org/protobuf/cmd/protoc-gen-go@v1.33.0
protoc-gen-go-grpc=google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.3.0
actionlint=github.com/rhysd/actionlint/cmd/actionlint@latest
gitleaks=github.com/zricethezav/gitleaks/v8@v8.21.2

default: build

mocks: install-tools ## Generate all mocks
	$(GO) generate ./...

test: install-tools test-run test-teardown

test-run: ## Run all unit tests
ifeq ($(filter 1,$(debug) $(RUNNER_DEBUG)),)
	$(eval TEST_CMD = SLOW=0 gotestsum --format pkgname-and-test-fails --)
	$(eval TEST_OPTIONS = -p=1 -v -failfast -shuffle=on -coverprofile=profile.out -covermode=atomic -coverpkg=./... -vet=all --timeout=15m)
else
	$(eval TEST_CMD = SLOW=0 go test)
	$(eval TEST_OPTIONS = -p=1 -v -failfast -shuffle=on -coverprofile=profile.out -covermode=atomic -coverpkg=./... -vet=all --timeout=15m)
endif
ifeq ($(RACE_ENABLED), true)
	$(eval TEST_OPTIONS := $(TEST_OPTIONS) -race)
endif
ifdef package
ifdef exclude
	$(eval FILES = `go list ./$(package)/... | egrep -iv '$(exclude)'`)
	$(TEST_CMD) -count=1 $(TEST_OPTIONS) $(FILES) && touch $(TESTFILE) || true
else
	$(TEST_CMD) $(TEST_OPTIONS) ./$(package)/... && touch $(TESTFILE) || true
endif
else ifdef exclude
	$(eval FILES = `go list ./... | egrep -iv '$(exclude)'`)
	$(TEST_CMD) -count=1 $(TEST_OPTIONS) $(FILES) && touch $(TESTFILE) || true
else
	$(TEST_CMD) -count=1 $(TEST_OPTIONS) ./... && touch $(TESTFILE) || true
endif

test-warehouse-integration:
	$(eval TEST_PATTERN = 'TestIntegration')
	$(eval TEST_CMD = SLOW=1 go test)
	$(eval TEST_OPTIONS = -v -p 8 -timeout 30m -count 1 -run $(TEST_PATTERN) -coverprofile=profile.out -covermode=atomic -coverpkg=./...)
ifeq ($(RACE_ENABLED), true)
	$(eval TEST_OPTIONS := $(TEST_OPTIONS) -race)
endif
	$(TEST_CMD) $(TEST_OPTIONS) ./$(package)/... && touch $(TESTFILE) || true

test-warehouse: test-warehouse-integration test-teardown

test-teardown:
	@if [ -f "$(TESTFILE)" ]; then \
    	echo "Tests passed, tearing down..." ;\
		rm -f $(TESTFILE) ;\
		echo "mode: atomic" > coverage.txt ;\
		find . -name "profile.out" | while read file; do grep -v 'mode: atomic' $${file} >> coverage.txt; rm -f $${file}; done ;\
	else \
    	rm -f coverage.txt coverage.html ; find . -name "profile.out" | xargs rm -f ;\
		echo "Tests failed :-(" ;\
		exit 1 ;\
	fi

coverage:
	go tool cover -html=coverage.txt -o coverage.html

test-with-coverage: test coverage

build: ## Build rudder-server binary
	$(eval BUILD_OPTIONS = )
ifeq ($(RACE_ENABLED), TRUE)
	$(eval BUILD_OPTIONS = $(BUILD_OPTIONS) -race -o rudder-server-with-race)
endif
	$(GO) build $(BUILD_OPTIONS) -a -installsuffix cgo -ldflags="$(LDFLAGS)"
	$(GO) build -o build/wait-for-go/wait-for-go build/wait-for-go/wait-for.go
	$(GO) build -o build/regulation-worker ./regulation-worker/cmd/

run: ## Run rudder-server using go run
	$(GO) run main.go

run-mt: ## Run rudder-server in multi-tenant deployment type
	$(GO) run ./cmd/devtool etcd mode --no-wait normal
	$(GO) run ./cmd/devtool etcd workspaces --no-wait none
	DEPLOYMENT_TYPE=MULTITENANT $(GO) run main.go

help: ## Show the available commands
	@grep -E '^[0-9a-zA-Z_-]+:.*?## .*$$' ./Makefile | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'


install-tools:
	$(GO) install $(mockgen)
	$(GO) install $(protoc-gen-go)
	$(GO) install $(protoc-gen-go-grpc)
	$(GO) install $(gotestsum)

.PHONY: lint
lint: fmt  ## Run linters on all go files
	$(GO) run $(GOLANGCI) run -v
	$(GO) run $(actionlint)
	@$(MAKE) sec

.PHONY: fmt
fmt: install-tools ## Formats all go files
	$(GO) run $(gofumpt) -l -w -extra  .
	find . -type f -name '*.go' -exec grep -L -E 'Code generated by .*\. DO NOT EDIT.' {} + | xargs $(GO) run $(goimports) -format-only -w -local=github.com/rudderlabs
	$(GO) run .github/tools/matrixchecker/main.go
	./build/docker-go-version.sh Dockerfile ./suppression-backup-service/Dockerfile

.PHONY: proto
proto: install-tools ## Generate protobuf files
	protoc --go_out=paths=source_relative:. proto/**/*.proto
	protoc --go-grpc_out=paths=source_relative:. proto/**/*.proto

.PHONY: bench-kafka
bench-kafka:
	go test -count 1 -run BenchmarkCompression -bench=. -benchmem ./services/streammanager/kafka/client

.PHONY: generate-openapi-spec
generate-openapi-spec: install-tools
	docker run --rm \
	  -v ${PWD}:${MOUNT_PATH} openapitools/openapi-generator-cli:v7.3.0 generate \
	  -i ${MOUNT_PATH}/gateway/openapi.yaml \
	  -g html2 \
	  -o ${MOUNT_PATH}/gateway/openapi

.PHONY: sec
sec: ## Run security checks
	$(GO) run $(gitleaks) detect .
	$(GO) run $(govulncheck) ./...
